package com.atguigu.gmall.payment.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.payment.service.WxPayService;
import com.atguigu.gmall.payment.util.HttpClient;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;

/***
 * 微信支付的service层的实现类
 */
@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

    @Value("${weixin.pay.appid}")
    private String appid;

    @Value("${weixin.pay.partner}")
    private String partner;

    @Value("${weixin.pay.partnerkey}")
    private String partnerkey;

    @Value("${weixin.pay.notifyUrl}")
    private String notifyUrl;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 获取支付地址（二维码）
     *
     * @param payUrlParamMap
     * @return
     */
    @Override
    public String getPayUrl(Map<String, String> payUrlParamMap) {
        //初始化map
        Map<String, String> paramsMap = new HashMap<>();

        //1 封装微信下单所需要的参数
        paramsMap.put("appid", appid);
        paramsMap.put("mch_id", partner);
        paramsMap.put("nonce_str", WXPayUtil.generateNonceStr());
        paramsMap.put("body", payUrlParamMap.get("body"));
        paramsMap.put("out_trade_no", payUrlParamMap.get("orderId"));
        paramsMap.put("total_fee", payUrlParamMap.get("amount"));
        paramsMap.put("spbill_create_ip", "192.168.200.1");
        paramsMap.put("notify_url", notifyUrl);
        paramsMap.put("trade_type", "NATIVE");

        //封装附加参数attach：routingKey、username
        Map<String, String> attachMap = new HashMap<>();
        attachMap.put("routingKey", payUrlParamMap.get("routingKey"));
        if (!StringUtils.isEmpty(payUrlParamMap.get("username"))) {
            //不为空，说明传入了username
            attachMap.put("username", payUrlParamMap.get("username"));
        }

        //封装获取微信支付地址的attach参数
        paramsMap.put("attach", JSONObject.toJSONString(attachMap));

        try {
            //把map转换成xml格式，并添加签名
            String paramXml = WXPayUtil.generateSignedXml(paramsMap, partnerkey);
            //声明调用地址
            String wxPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

            //2 调用微信下单的接口
            //声明发送请求工具类
            HttpClient httpClient = new HttpClient(wxPayUrl);
            //设置请求协议
            httpClient.setHttps(true);
            //设置参数
            httpClient.setXmlParam(paramXml);
            //发送post请求
            httpClient.post();

            //3 获取调用接口后传来的内容
            String resultXmlString = httpClient.getContent();
            //转行成string
            Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXmlString);
            //判断调用是否成功
            if (!resultMap.get("return_code").equals("SUCCESS") || !resultMap.get("result_code").equals("SUCCESS")) {
                //失败的情况
                return null;
            }

            //4 返回二维码
            return resultMap.get("code_url");
        } catch (Exception e) {
            log.error("请求微信支付接口获取支付地址（二维码）失败，订单号为：" + payUrlParamMap.get("orderId"));
            log.error("请求微信支付接口获取支付地址（二维码）失败，错误原因为：" + e.getMessage());
        }
        return null;
    }

    /**
     * 查询订单的支付结果
     *
     * @param orderId
     * @return
     */
    @Override
    public Map<String, String> getWxPayResult(String orderId) {
        //初始化map
        Map<String, String> paramMap = new HashMap<>();

        //1 封装查询订单的支付结果的参数
        paramMap.put("appid", appid);
        paramMap.put("mch_id", partner);
        paramMap.put("out_trade_no", orderId);
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());

        try {
            //将map转成xml，并增加签名
            String paramXmlString = WXPayUtil.generateSignedXml(paramMap, partnerkey);
            //声明请求地址
            String url = "https://api.mch.weixin.qq.com/pay/orderquery";
            //创建发送请求工具对象
            HttpClient httpClient = new HttpClient(url);
            //设置请求参数
            httpClient.setXmlParam(paramXmlString);
            //设置请求协议
            httpClient.setHttps(true);

            //2 向微信查询订单的支付结果的接口发送post请求
            httpClient.post();
            //获取到返回内容
            String resultXmlString = httpClient.getContent();
            //转换成map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXmlString);

            //3 返回结果
            return resultMap;

        } catch (Exception e) {
            log.error("查询微信支付结果失败，订单号为：" + orderId);
            log.error("查询微信支付结果失败，原因为：" + e.getMessage());
        }
        return null;
    }

    /**
     * 支付结束回调通知
     *
     * @param request
     * @return
     */
    @Override
    public String notifyCallback(HttpServletRequest request) {
        try {
//            //1 获取回掉通知中的内容
//            ServletInputStream is = request.getInputStream();
//
//            //2 将数据读取到程序中
//            //创建输出流
//            ByteArrayOutputStream os = new ByteArrayOutputStream();
//            //定义一个缓冲区
//            byte[] buffer = new byte[1024];
//            //初始化长度
//            int len = 0;
//            //读取
//            while ((len = is.read(buffer)) != -1) {
//                os.write(buffer, 0, len);
//            }
//            //获取输出流中的字节码
//            byte[] bytes = os.toByteArray();
//            //转换为字符串
//            String notifyResultXmlString = new String(bytes);
//            //转换为map
//            Map<String, String> payNotifyResultMap = WXPayUtil.xmlToMap(notifyResultXmlString);

            //省钱策略
            String payNotifyResultJsonString =
                    "{\"transaction_id\":\"4200001768202303169755617292\",\"nonce_str\":\"91b166861c5242ecae715b0dc383351e\",\"bank_type\":\"OTHERS\",\"openid\":\"oHwsHuLiGIvde5A_NAtpjYqXOBRw\",\"sign\":\"3B3C13240B7AFB894A06A8AF636B547B\",\"fee_type\":\"CNY\",\"mch_id\":\"1558950191\",\"cash_fee\":\"1\",\"out_trade_no\":\"33eef3cbc0a84d4193c06e69e4ade59f\",\"appid\":\"wx74862e0dfcf69954\",\"total_fee\":\"1\",\"trade_type\":\"NATIVE\",\"result_code\":\"SUCCESS\",\"attach\":\"{\\\"routingKey\\\":\\\"order.seckill.pay\\\",\\\"username\\\":\\\"jyw\\\"}\",\"time_end\":\"20230316153227\",\"is_subscribe\":\"N\",\"return_code\":\"SUCCESS\"}";
            //反序列化
            Map<String, String> payNotifyResultMap = JSONObject.parseObject(payNotifyResultJsonString, Map.class);

//            //转换为json
//            String payNotifyResultJsonString = JSONObject.toJSONString(payNotifyResultMap);
//            System.out.println(JSONObject.toJSONString(payNotifyResultMap));
//            //关闭资源
//            is.close();
//            os.close();

            //获取附加参数的数据
            String attachJsonString = payNotifyResultMap.get("attach");
            //反序列化
            Map<String, String> attachMap = JSONObject.parseObject(attachJsonString, Map.class);

            //支付成功，发送消息（mq）异步修改订单状态
            rabbitTemplate.convertAndSend(
                    "order_pay_exchange",
                    attachMap.get("routingKey"),
                    payNotifyResultJsonString);

            //初始响应数据的map
            Map<String, String> returnMap = new HashMap<>();
            //封装响应数据
            returnMap.put("return_code", "SUCCESS");
            returnMap.put("return_msg", "OK");

            //3 支付成功，响应微信数据
            return WXPayUtil.mapToXml(returnMap);

        } catch (Exception e) {
            log.error("获取支付后回调通知内容失败，原因为：" + e.getMessage());
        }

        return null;
    }
}
